#pragma once

#include <bitset>
#include "graphics/Rect2D.h"

class GameManager;

/*
	TODO:
	1. serialize input
		- Sync all keyboard state and mouse state (buttons and pos)
	2. Sync input across networked players
	3. handle the input 
		- Rewrite the get classes to use the serialized state
*/

enum Key			   { keyboard_w, keyboard_a, keyboard_s, keyboard_d, keyboard_SPACE, keyboard_LSHIFT, keyboard_pluss, keyboard_minus, keyboard_esc, KEYS_LEN};
static int key_ind[] = { 'W',		 'A',	     'S',        'D',        GLFW_KEY_SPACE, GLFW_KEY_LEFT_SHIFT, GLFW_KEY_KP_ADD, GLFW_KEY_KP_SUBTRACT, GLFW_KEY_ESCAPE};

enum MouseButton		 { mouse_left,			   mouse_right,			   MOUSE_LEN};
static int mouse_ind[] = { GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT};

class InputManager
{
public:

	static InputManager* getInstance();

    ~InputManager();

    void update();
    void encode(std::vector<unsigned char>& targetBuf, unsigned int offset);
	void decode(std::vector<unsigned char>& serializedBuf);
    bool isKeyClicked(Key key);
	static bool isKeyClickedLocal(int key);
    bool isKeyPressed(Key key);
    bool isMouseClicked(MouseButton mouseButton);
    bool isMousePressed(MouseButton mouseButton);
    glm::dvec2 getMousePos();
	void setMousePos(const glm::dvec2 & pos);
    glm::dvec2 getMouseMoveDelta() { return mouseMoveDelta; }
 	
private:

	static InputManager* instance;
	InputManager();
    
    glm::dvec2 initialMousePos;
    glm::dvec2 mouseMoveDelta;
 	//std::vector<unsigned int> keys;
    static const int GAME_KEY_C = 0;
    static const int N_KEYS = 1;
    std::bitset<KEYS_LEN> keyPrevList;
    std::bitset<8>    mouseButPrevList;

	std::vector<int> keyboardState;
	std::vector<int> mouseButtonState;
	double			 mousePosState[2];
};
